﻿/**
 * Copyright (c) 2013 Nokia Corporation.
 */

using System;
using System.Collections.Generic;
using System.Device.Location;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Dradis
{
    /// <summary>
    /// Provides creating and parsing of messages based on a very simple
    /// custom protocol.
    /// </summary>
    class MessageProtocol
    {
        // Constants
        private const String MessageStarter = "Dradis";
        private const char MessageWrapperDelimiter = '*';
        private const char MessageSplitterDelimiter = ';';
        private const char DefaultDecimalSeparatorChar = '.';

        // Members
        private static NumberFormatInfo _numberFormatInfo = new NumberFormatInfo();

        public static void Init()
        {
            _numberFormatInfo.NumberDecimalSeparator = DefaultDecimalSeparatorChar.ToString();
        }

        /// <summary>
        /// Creates a message.
        /// </summary>
        /// <param name="type">The user object type.</param>
        /// <param name="location">The user location.</param>
        /// <param name="channel">A Twitter channel.</param>
        /// <returns></returns>
        public static String CreateMessage(User.ObjectType type, GeoCoordinate location, String channel)
        {
            StringBuilder sb = new StringBuilder();
            String delimiter = MessageSplitterDelimiter + " ";
            sb.Append(MessageWrapperDelimiter);
            sb.Append(MessageStarter);
            sb.Append(delimiter);
            sb.Append((type == User.ObjectType.Raider) ? "Cylon" : "Human");
            sb.Append(delimiter);
            sb.Append(location.Latitude.ToString(_numberFormatInfo));
            sb.Append(delimiter);
            sb.Append(location.Longitude.ToString(_numberFormatInfo));
            sb.Append(MessageWrapperDelimiter);
            //sb.Append(" http://developer.nokia.com ");
            sb.Append(" ");
            sb.Append(TwitterManager.HashtagChar);
            sb.Append(channel);
            return sb.ToString();
        }

        /// <summary>
        /// Parses the details from the given message and extracts the data to
        /// the given User instance.
        /// </summary>
        /// <param name="message">The message to parse.</param>
        /// <param name="user">The user instance.</param>
        /// <returns>True if successful, false otherwise.</returns>
        public static bool ParseMessage(String message, User user)
        {
            if (message == null)
            {
                return false;
            }

            String[] splitted = message.Split(MessageWrapperDelimiter);
            bool ok = false;

            foreach (String part in splitted)
            {
                if (part.StartsWith(MessageStarter))
                {
                    splitted = part.Split(MessageSplitterDelimiter);
                    ok = true;
                    break;
                }
            }

            User.ObjectType type = User.ObjectType.Unknown;
            GeoCoordinate coordinate = null;

            if (ok)
            {
                try
                {
                    if (splitted[1].Contains("Cylon"))
                    {
                        type = User.ObjectType.Raider;
                    }
                    else
                    {
                        type = User.ObjectType.Viper;
                    }
                }
                catch (Exception e)
                {
                    System.Diagnostics.Debug.WriteLine("MessageProtocol::ParseMessage(): " + e.ToString());
                    ok = false;
                }

                try
                {
                    coordinate = new GeoCoordinate(
                        Double.Parse(splitted[2].Trim().Replace(',', DefaultDecimalSeparatorChar), _numberFormatInfo),
                        double.Parse(splitted[3].Trim().Replace(',', DefaultDecimalSeparatorChar), _numberFormatInfo));
                }
                catch (Exception e)
                {
                    System.Diagnostics.Debug.WriteLine("MessageProtocol::ParseMessage(): " + e.ToString());
                    ok = false;
                }
            }

            if (user != null)
            {
                user.Type = type;

                if (coordinate != null)
                {
                    user.Location = coordinate;
                }
            }

            return ok;
        }

        /// <summary>
        /// Checks whether the given message matches the protocol or not.
        /// </summary>
        /// <param name="message">The message to check.</param>
        /// <returns>True if the message matches the protocol, false otherwise.</returns>
        public static bool MatchesProtocol(String message)
        {
            return ParseMessage(message, null);
        }
    }
}
